package com.example.system.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.starter.util.ExceptionUtil;
import com.example.system.convert.RoleConvert;
import com.example.system.dto.RoleDto;
import com.example.system.entity.Role;
import com.example.system.entity.RoleAuthorityJoin;
import com.example.system.mapper.RoleMapper;
import com.example.system.service.IRoleService;
import com.example.system.vo.RoleVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 *
 * @author 王令
 * @since 2022-08-05
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Override
    public void create(RoleDto roleDto) {
        Role role = RoleConvert.INSTANCE.toRole(roleDto);
        assertUniqueRecord(role);
        this.save(role);
    }

    @Override
    public void update(RoleDto roleDto) {
        Role role = RoleConvert.INSTANCE.toRole(roleDto);
        assertUniqueRecord(role);
        this.updateById(role);
    }

    @Transactional
    @Override
    public void grantAuthorities(Long roleId, List<Long> authoritiesId) {
        baseMapper.removeWithAuthorityJoins(roleId);
        if (ObjUtil.isNotEmpty(authoritiesId)) {
            baseMapper.addWithAuthorityJoins(roleId, authoritiesId);
        }
    }

    @Override
    public List<Role> listByUserId(Long userId) {
        return baseMapper.listByUserId(userId);
    }

    @Override
    public List<Role> listByUsername(String username) {
        return baseMapper.listByUsername(username);
    }

    @Override
    public List<RoleVo> listAll() {
        return RoleConvert.INSTANCE.toRoleVoList(baseMapper.selectList(Wrappers.emptyWrapper()));
    }


    @Override
    public List<Long> listAuthorityIdByRoleId(Long roleId) {
        List<RoleAuthorityJoin> authoritiesJoinsVos = baseMapper.listWithAuthorityJoinByRoleId(roleId);
        if (ObjectUtil.isEmpty(authoritiesJoinsVos)) {
            return ListUtil.empty();
        }
        return authoritiesJoinsVos.stream().map(RoleAuthorityJoin::getAuthorityId).collect(Collectors.toList());
    }

    private void assertUniqueRecord(Role role) {
        LambdaQueryWrapper<Role> wrapper = Wrappers.<Role>lambdaQuery()
                .eq(Role::getCode, role.getCode())
                .ne(role.getId() != null, Role::getId, role.getId());
        Role one = baseMapper.selectOne(wrapper);
        if (one != null) {
            throw ExceptionUtil.wrap("角色编码已存在");
        }
    }

}
